import {CodePlatformMethodMap} from "./constant";
import {Platform} from './Platform';
import {CodePlatformHumpMethod} from "./types";

// 为PlatformChain添加动态方法类型支持
type PlatformMethodType<T> = {
  [K in CodePlatformHumpMethod]: (callback: () => T) => PlatformChain<T> & PlatformMethodType<T>;
};

// 动态添加的方法不能在类定义时进行类型检查，因此使用类型交集
export class PlatformChain<T = any> {
  private readonly defaultCallback?: () => any;
  private platformCallbacks: Map<string, () => any> = new Map();
  private result: any = undefined;
  private executed: boolean = false;

  // 实现索引签名，允许使用动态属性
  [key: string]: any;

  private constructor(defaultCallback?: () => any) {
    this.defaultCallback = defaultCallback;
  }

  /**
   * 开始构建平台判断链
   * @param defaultCallback 默认回调函数，当没有匹配的平台时执行
   * @returns PlatformChain实例
   */
  public static with<T>(defaultCallback?: () => T): PlatformChain<T> & PlatformMethodType<T> {
    return new PlatformChain<T>(defaultCallback) as PlatformChain<T> & PlatformMethodType<T>;
  }

  /**
   * 设置平台回调
   * @param platforms 平台列表
   * @param callback 回调函数
   * @returns 当前实例，支持链式调用
   */
  public case(platforms: CodePlatformHumpMethod[], callback: () => T): PlatformChain<T> & PlatformMethodType<T> {
    platforms.forEach(platform => {
      this.setPlatformCallback(platform, callback);
    });
    return this as unknown as PlatformChain<T> & PlatformMethodType<T>;
  }

  /**
   * 执行匹配的平台回调并返回结果
   * @returns 执行结果
   */
  public exec(): T {
    if (!this.executed) {
      this.execute();
    }
    return this.result;
  }

  /**
   * 为特定平台设置回调
   * @param platform 平台标识
   * @param callback 回调函数
   * @returns 当前实例，支持链式调用
   */
  public setPlatformCallback<R>(platform: string, callback: () => R): PlatformChain<R> & PlatformMethodType<T> {
    this.platformCallbacks.set(platform, callback);
    return this as unknown as PlatformChain<R> & PlatformMethodType<T>;
  }

  /**
   * 执行平台判断逻辑
   * @returns 当前实例，支持链式调用
   */
  private execute(): PlatformChain<T> {
    const currentPlatform = Platform.getCodePlatform();

    // 检查是否有匹配的平台回调
    if (this.platformCallbacks.has(currentPlatform)) {
      this.result = this.platformCallbacks.get(currentPlatform)!();
    }
    // 检查是否有通用小程序回调
    else if (Platform.isMp() && this.platformCallbacks.has('MP')) {
      this.result = this.platformCallbacks.get('MP')!();
    }
    // 执行默认回调
    else if (this.defaultCallback) {
      this.result = this.defaultCallback();
    }

    this.executed = true;
    return this;
  }
}

// 为PlatformChain类动态添加平台方法
Object.keys(CodePlatformMethodMap).forEach((platform) => {
  (PlatformChain.prototype)[platform] = function <R>(this: PlatformChain<any>, callback: () => R): PlatformChain<R> & PlatformMethodType<R> {
    return this.setPlatformCallback(CodePlatformMethodMap[platform as CodePlatformHumpMethod], callback);
  };
});
